{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "hIDdGw6hepiF"
      },
      "source": [
        "# Basic embedding retrieval with Chroma\n",
        "\n",
        "This notebook demonstrates the most basic use of Chroma to store and retrieve information using embeddings. This core building block is at the heart of many powerful AI applications.\n",
        "\n",
        "## What are embeddings?\n",
        "\n",
        "Embeddings are the A.I-native way to represent any kind of data, making them the perfect fit for working with all kinds of A.I-powered tools and algorithms. They can represent text, images, and soon audio and video.\n",
        "\n",
        "To create an embedding, data is fed into an embedding model, which outputs vectors of numbers. The model is trained in such a way that 'similar' data, e.g. text with similar meanings, or images with similar content, will produce vectors which are nearer to one another, than those which are dissimilar.\n",
        "\n",
        "## Embeddings and retrieval\n",
        "\n",
        "We can use the similarity property of embeddings to search for and retrieve information. For example, we can find documents relevant to a particular topic, or images similar to a given image. Rather than searching for keywords or tags, we can search by finding data with similar semantic meaning.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "R1nkKfEUepiH"
      },
      "outputs": [],
      "source": [
        "%pip install -Uq chromadb numpy datasets"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "6lfVmRQlepiI"
      },
      "source": [
        "## Example Dataset\n",
        "\n",
        "As a demonstration we use the [SciQ dataset](https://arxiv.org/abs/1707.06209), available from [HuggingFace](https://huggingface.co/datasets/sciq).\n",
        "\n",
        "Dataset description, from HuggingFace:\n",
        "\n",
        "> The SciQ dataset contains 13,679 crowdsourced science exam questions about Physics, Chemistry and Biology, among others. The questions are in multiple-choice format with 4 answer options each. For the majority of the questions, an additional paragraph with supporting evidence for the correct answer is provided.\n",
        "\n",
        "In this notebook, we will demonstrate how to retrieve supporting evidence for a given question.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "N-wEyOQzepiI",
        "outputId": "f5476e9f-1732-4d57-9916-3c1d8f85b71b",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Number of questions with support:  10481\n"
          ]
        }
      ],
      "source": [
        "# Get the SciQ dataset from HuggingFace\n",
        "from datasets import load_dataset\n",
        "\n",
        "dataset = load_dataset(\"sciq\", split=\"train\")\n",
        "\n",
        "# Filter the dataset to only include questions with a support\n",
        "dataset = dataset.filter(lambda x: x[\"support\"] != \"\")\n",
        "\n",
        "print(\"Number of questions with support: \", len(dataset))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "s8wXeIZKepiI"
      },
      "source": [
        "## Loading the data into Chroma\n",
        "\n",
        "Chroma comes with a built-in embedding model, which makes it simple to load text.\n",
        "We can load the SciQ dataset into Chroma with just a few lines of code.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "YrcrqRzWepiI"
      },
      "outputs": [],
      "source": [
        "# Import Chroma and instantiate a client. The default Chroma client is ephemeral, meaning it will not save to disk.\n",
        "import chromadb\n",
        "\n",
        "client = chromadb.Client()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "JFKONr2mepiI"
      },
      "outputs": [],
      "source": [
        "# Create a new Chroma collection to store the supporting evidence. We don't need to specify an embedding fuction, and the default will be used.\n",
        "collection = client.create_collection(\"sciq_supports\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "LNE9l1DTepiJ",
        "outputId": "f4d6485e-f125-4b38-ac87-9787b22962fe",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "/root/.cache/chroma/onnx_models/all-MiniLM-L6-v2/onnx.tar.gz: 100%|██████████| 79.3M/79.3M [00:01<00:00, 79.0MiB/s]\n"
          ]
        }
      ],
      "source": [
        "# Embed and store the first 100 supports for this demo\n",
        "collection.add(\n",
        "    ids=[str(i) for i in range(0, 100)],  # IDs are just strings\n",
        "    documents=dataset[\"support\"][:100],\n",
        "    metadatas=[{\"type\": \"support\"} for _ in range(0, 100)\n",
        "    ],\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "1XOm1G9bepiJ"
      },
      "source": [
        "## Querying the data\n",
        "\n",
        "Once the data is loaded, we can use Chroma to find supporting evidence for the questions in the dataset.\n",
        "In this example, we retrieve the most relevant result according to the embedding similarity score.\n",
        "\n",
        "Chroma handles computing similarity and finding the most relevant results for you, so you can focus on building your application.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ozGyfQHXepiJ"
      },
      "outputs": [],
      "source": [
        "results = collection.query(\n",
        "    query_texts=dataset[\"question\"][:10],\n",
        "    n_results=1)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "cMgxpE6AepiJ"
      },
      "source": [
        "we display the query questions along with their retrieved supports"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "kjw-Rn_ZepiJ",
        "outputId": "ea184fce-530a-4968-9f3c-3d95f9ce99bc",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Question: What type of organism is commonly used in preparation of foods such as cheese and yogurt?\n",
            "Retrieved support: Agents of Decomposition The fungus-like protist saprobes are specialized to absorb nutrients from nonliving organic matter, such as dead organisms or their wastes. For instance, many types of oomycetes grow on dead animals or algae. Saprobic protists have the essential function of returning inorganic nutrients to the soil and water. This process allows for new plant growth, which in turn generates sustenance for other organisms along the food chain. Indeed, without saprobe species, such as protists, fungi, and bacteria, life would cease to exist as all organic carbon became “tied up” in dead organisms.\n",
            "\n",
            "Question: What phenomenon makes global winds blow northeast to southwest or the reverse in the northern hemisphere and northwest to southeast or the reverse in the southern hemisphere?\n",
            "Retrieved support: Without Coriolis Effect the global winds would blow north to south or south to north. But Coriolis makes them blow northeast to southwest or the reverse in the Northern Hemisphere. The winds blow northwest to southeast or the reverse in the southern hemisphere.\n",
            "\n",
            "Question: Changes from a less-ordered state to a more-ordered state (such as a liquid to a solid) are always what?\n",
            "Retrieved support: Summary Changes of state are examples of phase changes, or phase transitions. All phase changes are accompanied by changes in the energy of a system. Changes from a more-ordered state to a less-ordered state (such as a liquid to a gas) areendothermic. Changes from a less-ordered state to a more-ordered state (such as a liquid to a solid) are always exothermic. The conversion of a solid to a liquid is called fusion (or melting). The energy required to melt 1 mol of a substance is its enthalpy of fusion (ΔHfus). The energy change required to vaporize 1 mol of a substance is the enthalpy of vaporization (ΔHvap). The direct conversion of a solid to a gas is sublimation. The amount of energy needed to sublime 1 mol of a substance is its enthalpy of sublimation (ΔHsub) and is the sum of the enthalpies of fusion and vaporization. Plots of the temperature of a substance versus heat added or versus heating time at a constant rate of heating are calledheating curves. Heating curves relate temperature changes to phase transitions. A superheated liquid, a liquid at a temperature and pressure at which it should be a gas, is not stable. A cooling curve is not exactly the reverse of the heating curve because many liquids do not freeze at the expected temperature. Instead, they form a supercooled liquid, a metastable liquid phase that exists below the normal melting point. Supercooled liquids usually crystallize on standing, or adding a seed crystal of the same or another substance can induce crystallization.\n",
            "\n",
            "Question: What is the least dangerous radioactive decay?\n",
            "Retrieved support: All radioactive decay is dangerous to living things, but alpha decay is the least dangerous.\n",
            "\n",
            "Question: Kilauea in hawaii is the world’s most continuously active volcano. very active volcanoes characteristically eject red-hot rocks and lava rather than this?\n",
            "Retrieved support: Example 3.5 Calculating Projectile Motion: Hot Rock Projectile Kilauea in Hawaii is the world’s most continuously active volcano. Very active volcanoes characteristically eject red-hot rocks and lava rather than smoke and ash. Suppose a large rock is ejected from the volcano with a speed of 25.0 m/s and at an angle 35.0º above the horizontal, as shown in Figure 3.40. The rock strikes the side of the volcano at an altitude 20.0 m lower than its starting point. (a) Calculate the time it takes the rock to follow this path. (b) What are the magnitude and direction of the rock’s velocity at impact?.\n",
            "\n",
            "Question: When a meteoroid reaches earth, what is the remaining object called?\n",
            "Retrieved support: Meteoroids are smaller than asteroids, ranging from the size of boulders to the size of sand grains. When meteoroids enter Earth’s atmosphere, they vaporize, creating a trail of glowing gas called a meteor. If any of the meteoroid reaches Earth, the remaining object is called a meteorite.\n",
            "\n",
            "Question: What kind of a reaction occurs when a substance reacts quickly with oxygen?\n",
            "Retrieved support: A combustion reaction occurs when a substance reacts quickly with oxygen (O 2 ). For example, in the Figure below , charcoal is combining with oxygen. Combustion is commonly called burning, and the substance that burns is usually referred to as fuel. The products of a complete combustion reaction include carbon dioxide (CO 2 ) and water vapor (H 2 O). The reaction typically gives off heat and light as well. The general equation for a complete combustion reaction is:.\n",
            "\n",
            "Question: Organisms categorized by what species descriptor demonstrate a version of allopatric speciation and have limited regions of overlap with one another, but where they overlap they interbreed successfully?.\n",
            "Retrieved support: Ring species Ring species demonstrate a version of allopatric speciation. Imagine populations of the species A. Over the geographic range of A there exist a number of subpopulations. These subpopulations (A1 to A5) and (Aa to Ae) have limited regions of overlap with one another but where they overlap they interbreed successfully. But populations A5 and Ae no longer interbreed successfully – are these populations separate species?  In this case, there is no clear-cut answer, but it is likely that in the link between the various populations will be broken and one or more species may form in the future. Consider the black bear Ursus americanus. Originally distributed across all of North America, its distribution is now much more fragmented. Isolated populations are free to adapt to their own particular environments and migration between populations is limited. Clearly the environment in Florida is different from that in Mexico, Alaska, or Newfoundland. Different environments will favor different adaptations. If, over time, these populations were to come back into contact with one another, they might or might not be able to interbreed successfully - reproductive isolation may occur and one species may become many.\n",
            "\n",
            "Question: Alpha emission is a type of what?\n",
            "Retrieved support: One type of radioactivity is alpha emission. What is an alpha particle? What happens to an alpha particle after it is emitted from an unstable nucleus?.\n",
            "\n",
            "Question: What is the stored food in a seed called?\n",
            "Retrieved support: The stored food in a seed is called endosperm . It nourishes the embryo until it can start making food on its own.\n",
            "\n"
          ]
        }
      ],
      "source": [
        "# Print the question and the corresponding support\n",
        "for i, q in enumerate(dataset['question'][:10]):\n",
        "    print(f\"Question: {q}\")\n",
        "    print(f\"Retrieved support: {results['documents'][i][0]}\")\n",
        "    print()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "AKNEJjHaepiJ"
      },
      "source": [
        "## What's next?\n",
        "\n",
        "Check out the Chroma documentation to [get started](https://docs.trychroma.com/getting-started) with building your own applications.\n",
        "\n",
        "The core embeddings based retrieval functionality demonstrated here is at the heart of many powerful AI applications, like using large language models with Chroma to [chat with your documents](https://github.com/chroma-core/chroma/tree/main/examples/chat_with_your_documents), as well as memory for agents like [BabyAgi](https://github.com/yoheinakajima/babyagi) and [Voyager](https://github.com/MineDojo/Voyager).\n",
        "\n",
        "Chroma is already integrated with many popular AI applications frameworks, including [LangChain](https://python.langchain.com/docs/integrations/vectorstores/chroma) and [LlamaIndex](https://gpt-index.readthedocs.io/en/latest/examples/vector_stores/ChromaIndexDemo.html).\n",
        "\n",
        "Join our community to learn more and get help with your projects: [Discord](https://discord.gg/MMeYNTmh3x) | [Twitter](https://twitter.com/trychroma)\n",
        "\n",
        "We are [hiring](https://trychroma.notion.site/careers-chroma-9d017c3007c7478ebd85bad854101497?pvs=4)!"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.10.12"
    },
    "orig_nbformat": 4,
    "colab": {
      "provenance": []
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}